﻿using NoDriverPrintHelperV1d0.Entity;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ZhangLogSysV1d0;

namespace NoDriverPrintHelperV1d0.Service
{
    public class EscPrinterV1d0
    {
        public string PrinterIp { get; set; }
        public int PrinterPort { get; set; }
        /// <summary>
        /// 用于连接打印机的套接字
        /// </summary>
        public TcpClient PrinterTcpClient = null;
        public TmU220EscPosPrintFunctionV1d0 WorkingPrinter = null;
        public ManualResetEvent PulseCheckTimeoutObject = new ManualResetEvent(false);
        public byte[] ByteMessage = new byte[1024];
        private static readonly object Lock_IsRunning = new object();
        private bool _IsRunning=false;
        /// <summary>
        /// 线程是否运行
        /// </summary>
        public bool IsRunning
        {
            get
            {
                lock (Lock_IsRunning)
                {
                    return _IsRunning;
                }
            }
            set
            {
                lock (Lock_IsRunning)
                {
                    _IsRunning = value;
                }
            }
        }
        private static readonly object Lock_IsOnLine = new object();
        public bool _IsOnLine=false;
        /// <summary>
        /// 打印机是否在线
        /// </summary>
        public bool IsOnLine
        {
            get
            {
                lock (Lock_IsOnLine)
                {
                    return _IsOnLine;
                }
            }
            set
            {
                lock (Lock_IsOnLine)
                {
                    _IsOnLine = value;
                }
            }
        }
        private static readonly object Lock_IsAvailable = new object();
        public bool _IsAvailable=false;
        /// <summary>
        /// 打印机是否可用
        /// </summary>
        public bool IsAvailable
        {
            get
            {
                lock (Lock_IsAvailable)
                {
                    return _IsAvailable;
                }
            }
            set
            {
                lock (Lock_IsAvailable)
                {
                    _IsAvailable = value;
                }
            }
        }

        /// <summary>
        /// 打印机状态
        /// </summary>
        private static readonly object Lock_PrinterStatus = new object();
        public int _PrinterStatus = 0;
        public int PrinterStatus
        {
            get
            {
                lock (Lock_PrinterStatus)
                {
                    return _PrinterStatus;
                }
            }
            set
            {
                lock (Lock_PrinterStatus)
                {
                    _PrinterStatus = value;
                }
            }
        }

/// <summary>
/// 检查结果为在线的次数
/// </summary>
public int CheckResultIsOnLineCount = 0;
        /// <summary>
        /// 检查结果为离线的次数
        /// </summary>
        public int CheckResultIsOffLineCount = 0;
        /// <summary>
        /// 检查结果为不可用的次数
        /// </summary>
        public int CheckResultIsUnAvailableCount = 0;
        ConcurrentQueue<PrintTaskV1d0> ToBeProcessTaskQueue = new ConcurrentQueue<PrintTaskV1d0>();
        ConcurrentQueue<PrintTaskV1d0> UnFinishedTaskQueue = new ConcurrentQueue<PrintTaskV1d0>();
        ConcurrentQueue<PrintTaskV1d0> FinishedTaskQueue = new ConcurrentQueue<PrintTaskV1d0>();

        private Thread Thread_Printer = null;
        /// <summary>
        /// 线程序号
        /// </summary>
        public int Thread_index = 0;

        /// <summary>
        /// 连接到打印机
        /// </summary>
        /// <param name="ip">ip地址</param>
        /// <param name="port">端口</param>
        /// <returns>是否连接成功</returns>
        private bool ConnectToPrinter(string ip, int port)
        {
            bool result = false;
            try
            {
                if (PrinterTcpClient == null || (PrinterTcpClient != null && (!PrinterTcpClient.Connected)))
                {
                    //2秒的连接超时
                    PrinterTcpClient = TcpClientWithTimeoutV1d0.TryConnect(ip, port, 2000);
                    if (PrinterTcpClient != null && PrinterTcpClient.Connected)
                    {
                        IsOnLine = true;
                        //-------
                        WorkingPrinter = new TmU220EscPosPrintFunctionV1d0(PrinterTcpClient);
                        //初始化打印机
                        result = WorkingPrinter.SendByteCommand(PrinterCmdUtilsV1d0.init_printer());
                        //使能自动状态回复ASB
                        result = WorkingPrinter.SendByteCommand(PrinterCmdUtilsV1d0.enableAsb());
                        //请求打印机传输纸张状态
                        result = WorkingPrinter.SendByteCommand(PrinterCmdUtilsV1d0.transferPrinterStatus());

                        //数据接收控制
                        ByteMessage = new byte[PrinterTcpClient.ReceiveBufferSize];
                        NetworkStream netStream = PrinterTcpClient.GetStream();
                        if (netStream.CanRead)
                        {
                            //异步读取数据
                            netStream.BeginRead(ByteMessage, 0, ByteMessage.Length, new AsyncCallback(SocketAsyncReadCallBack), netStream);
                        }
                        result = true;
                    }
                    else result = false;
                }
                else if (PrinterTcpClient != null && (PrinterTcpClient.Connected))
                {
                    result = true;
                }
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
                result = false;
            }
            return result;
        }
        /// <summary>
        /// 套接字异步网络流读取的回调函数
        /// </summary>
        /// <param name="iAsyncResult"></param>
        public void SocketAsyncReadCallBack(IAsyncResult iAsyncResult)
        {
            try
            {
                NetworkStream nStreamRead = iAsyncResult.AsyncState as NetworkStream;
                int countOfBytesRead = nStreamRead.EndRead(iAsyncResult);
                if (countOfBytesRead > 0)
                {
                    byte[] buffer = new byte[countOfBytesRead];
                    Array.Copy(ByteMessage, 0, buffer, 0, countOfBytesRead);
                    //对读取到的数据进行处理
                    ProcessPrinterMessage(buffer);
                    //继续进行下一次的异步读取,并将tcpClient套接字的网络数据流对象传递给回调函数
                    nStreamRead.BeginRead(ByteMessage, 0, ByteMessage.Length, new AsyncCallback(SocketAsyncReadCallBack), nStreamRead);
                }
                else
                {
                    nStreamRead.Close();
                    nStreamRead = null;
                }
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
        }
        /// <summary>
        /// 发送请求进纸器状态命令
        /// </summary>
        /// <returns></returns>
        private bool SendRequstPaperStatusCommand()
        {
            TmU220EscPosPrintFunctionV1d0 printer = new TmU220EscPosPrintFunctionV1d0(PrinterTcpClient);
            bool result = printer.SendByteCommand(PrinterCmdUtilsV1d0.transferPrinterStatus());
            return result;
        }
        /// <summary>
        /// 处理接收到的消息
        /// </summary>
        /// <param name="byteMessage"></param>
        private void ProcessPrinterMessage(byte[] byteMessage)
        {
            try
            {
                if (byteMessage.Length == 1)
                {
                    //打印机连接正常
                    IsOnLine = true;
                    //进纸器状态
                    byte printerStatus = byteMessage[0];

                    if(printerStatus==0) PrinterStatus = 1;//"进纸器状态正常";
                    else if((printerStatus& 3)>0) PrinterStatus = 2;//"打印纸将近末端";
                    else if ((printerStatus & 12) > 0) PrinterStatus = -1;//"打印机缺纸";                   
                }
                else if (byteMessage.Length == 4)
                {
                    //打印机连接正常
                    IsOnLine = true;
                    byte message0 = byteMessage[0];
                    byte message1 = byteMessage[1];
                    byte message2 = byteMessage[2];
                    byte message3 = byteMessage[3];//暂不使用
                    int printStatus0 = 0;
                    int printStatus1 = 0;
                    int printStatus2 = 0;
                    if ((message0 & 32) > 0) printStatus0 = -1;//卷纸盖被打开
                    else printStatus0 = 0;
                    if ((message1 & 4) > 0) printStatus1 = -4;//出现机械故障
                    else if ((message1 & 8) > 0) printStatus1 = -8;//自动裁纸器故障
                    else if ((message1 & 32) > 0) printStatus1 = -12;//不可恢复错误
                    else if ((message1 & 64) > 0) printStatus1 = -64;//可自动恢复错误
                    else printStatus1 = 0;

                    if ((message2 & 3) > 0) printStatus2 = 2;//"打印纸将近末端";
                    else if ((message2 & 12) > 0) printStatus2 = -12;//"打印机缺纸"; 
                    else printStatus2 = 1;//"进纸器状态正常";


                    if (printStatus0>0&& printStatus1 > 0 && printStatus2 > 0)
                    {
                        //stringMessage = "打印机状态正常";
                        PrinterStatus = 1;
                    }
                    else
                    {
                        PrinterStatus = -1;
                    }
                }
                if (IsOnLine==true && PrinterStatus > 0) IsAvailable = true;
                else IsAvailable = false;
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
                IsOnLine = false;
                PrinterStatus = -1;
                IsAvailable = false;
            }
            finally
            {
                //线程继续运行
                PulseCheckTimeoutObject.Set();
            }
        }
        /// <summary>
        /// 线程启动
        /// </summary>
        private void ThreadStart()
        {
            while (IsRunning)
            {
                try
                {
                    if (IsOnLine == false)
                    {
                        IsOnLine = ConnectToPrinter(PrinterIp, PrinterPort);
                    }
                    if (IsOnLine == true)
                    {
                        //心跳检测的超时信号置为阻塞
                        PulseCheckTimeoutObject.Reset();
                        //将请求进纸器状态作为心跳检测信号
                        SendRequstPaperStatusCommand();
                        //一旦接收到打印机发回的指令,PulseCheckTimeoutObject就被置为终止,线程可以继续
                        //只有在0.2秒内接收到心跳信号，才进行打印任务的处理
                        if (PulseCheckTimeoutObject.WaitOne(200, false))
                        {
                            //如果打印机可用
                            if (IsAvailable)
                            {
                                //从待处理打印任务队列取一个打印任务
                                PrintTaskItemV1d0 tastItem = new PrintTaskItemV1d0();
                                //如果取成功
                                //打印任务
                                SendPrintItemToPrinter(tastItem);
                                //如果没有取成功
                                //从未完成打印任务队列中取一个打印任务
                                //如果取成功
                                //打印该任务
                                //如果没有取成功进行下一个循环
                            }
                            else
                            {
                                //打印机检测到不可用的次数
                                CheckResultIsUnAvailableCount++;
                                //判断是否需要卸载任务
                                //如果需要卸载任务
                                //如果不需要卸载任务
                            }
                        }
                        else
                        {
                            //一旦超时(没有收到任何打印机返回的数据)，可以认为打印机离线,
                            IsOnLine = false;
                            //打印机检测到离线的次数
                            CheckResultIsOffLineCount++;
                        }
                    }
                    else if (IsOnLine == false)
                    {
                        CheckResultIsOffLineCount++;
                        //检查是否需要卸载任务
                        //如果需要卸载任务
                        //卸载任务
                        //如果不需要卸载任务,则进行下一个循环
                    }

                }
                catch (Exception ex)
                {
                    //连接超时
                    continue;
                }
            }
        }
        /// <summary>
        /// 检查是否在线
        /// </summary>
        /// <returns></returns>
        public bool CheckIsOnLine()
        {
            bool result = false;
            return result;
        }
        /// <summary>
        /// 检查是否可用
        /// </summary>
        /// <returns></returns>
        public bool CheckIsAvailable()
        {
            bool result = false;
            return result;
        }
        /// <summary>
        /// 检查是否需要卸载任务
        /// </summary>
        /// <returns></returns>
        public bool CheckIsNeedUninstallTask()
        {
            bool result = false;
            return result;
        }
        /// <summary>
        /// 处理任务
        /// </summary>
        public void ProcessTask()
        {
        }
        /// <summary>
        /// 分派任务到已完成任务列表
        /// </summary>
        public void AssignTaskToFinishedTaskQueue()
        {

        }
        /// <summary>
        /// 分派任务到未完成任务列表
        /// </summary>
        public void AssignTaskToUnFinishedTaskQueue()
        {

        }
        /// <summary>
        /// 处理打印任务，
        /// </summary>
        private void ProcessPrintTask(object state)
        {
            try
            {
                PrintTaskItemV1d0 taskItem = new PrintTaskItemV1d0();
                SendPrintItemToPrinter(taskItem);
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
        }
        public bool SendPrintItemToPrinter(PrintTaskItemV1d0 printTaskItem)
        {
            bool result = false;
            TmU220EscPosPrintFunctionV1d0 printer = new TmU220EscPosPrintFunctionV1d0(PrinterTcpClient);
            result = printer.SendPrintTaskItemToPrinter(printTaskItem);
            return result;
        }
        /// <summary>
        /// 卸载任务
        /// </summary>
        public void UninstallTask()
        {

        }
        /// <summary>
        /// 开始运行
        /// </summary>
        public void StartRunning()
        {
            this.Thread_Printer = new Thread(new System.Threading.ThreadStart(this.ThreadStart));
            this.IsRunning = true;
            //作为后台线程
            this.Thread_Printer.IsBackground = false;
            //启动线程
            this.Thread_Printer.Start();
        }
        /// <summary>
        /// 结束运行
        /// </summary>
        public void StopRunning()
        {
            this.IsRunning = false;
        }
        public void StopRunningPrepare()
        {

        }
    }

}
